package myserver

import (
	"fmt"
	"net"
	"strings"
)

type User struct {
	Name    string
	Address string
	Channel chan string
	conn    net.Conn
	server  *Server
}

func (user *User) ListenMessage() {
	for {
		msg := <-user.Channel
		user.conn.Write([]byte(msg + "\n"))
	}
}

func NewUser(conn net.Conn, server *Server) (user *User) {
	userAddr := conn.RemoteAddr().String()
	user = &User{
		Name:    userAddr,
		Address: userAddr,
		Channel: make(chan string),
		conn:    conn,
		server:  server,
	}
	go user.ListenMessage()

	return
}

func (user *User) Online() {
	user.server.mapLock.Lock()
	user.server.OnlineMap[user.Name] = user
	user.server.mapLock.Unlock()

	userinfo := user.GetUserinfo()
	user.server.Broadcast(userinfo + "online")
}

func (user *User) Offline() {
	user.server.mapLock.Lock()
	delete(user.server.OnlineMap, user.Name)
	user.server.mapLock.Unlock()

	user.server.Broadcast(user.GetUserinfo() + "offline")
}

func (user *User) DoMessage(msg string) {
	// re, _ := regexp.Compile(`(\w+)(\|\w+)*`)
	// name := re.FindStringSubmatch(msg)
	words := strings.Split(msg, "|")

	if words == nil {
		return
	}

	cmd := words[0]
	if cmd == "who" {
		user.server.mapLock.RLock()
		for _, tmp_user := range user.server.OnlineMap {
			user.SendMessage(tmp_user.GetUserinfo() + "is online")
		}
		user.server.mapLock.RUnlock()
	} else if cmd == "rename" {
		if len(words) < 2 {
			user.SendMessage("invalid rename!")
			return
		}
		user.rename(words[1])
		// return
	} else if cmd == "to" {
		if len(words) < 3 {
			user.SendMessage("invalid private message!")
			return
		}
		person_name := words[1]
		private_msg := words[2]
		if private_msg == "" {
			user.SendMessage("your message can't be null")
			return
		}
		user.server.mapLock.RLock()
		_, ok := user.server.OnlineMap[person_name]
		user.server.mapLock.RUnlock()

		if ok {
			user.server.OnlineMap[person_name].SendMessage(user.GetUserinfo() + private_msg)
		} else {
			user.SendMessage(fmt.Sprintf("user \"%s\" is not found", person_name))
		}

	} else {

		user.server.Broadcast(user.GetUserinfo() + msg)
	}

}

func (user *User) GetUserinfo() string {
	return fmt.Sprintf("[%s]%s: ", user.Address, user.Name)
}

func (user *User) SendMessage(msg string) {
	user.Channel <- msg
}

func (user *User) rename(name string) {
	if name == "" {
		user.SendMessage("your name can't be null")
		return
	}
	_, ok := user.server.OnlineMap[name]
	if ok {
		user.SendMessage(user.GetUserinfo() + "this name has existed")
		return
	}

	user.server.mapLock.Lock()
	delete(user.server.OnlineMap, user.Name)
	user.server.OnlineMap[name] = user
	user.server.mapLock.Unlock()
	user.Name = name
	user.SendMessage(user.GetUserinfo() + "rename successfully!")

}

func (user *User) Close() {
	close(user.Channel)
	user.conn.Close()
	user.Offline()
}
